package com.hb.common.base;

import lombok.Data;

import java.io.Serial;
import java.io.Serializable;
import java.time.Instant;

import com.hb.common.constant.SystemConstant;
import lombok.experimental.Accessors;

/*
* @Description: 接口返回数据格式
* @Author: YangTing
* @Date: 2025/6/25 上午10:07
**/
@Data
@Accessors(chain = true)
public class Result<T> implements Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    /**
     * 成功标志
     */
    private boolean success;

    /**
     * 返回处理消息
     */
    private String message;

    /**
     * 返回代码
     */
    private Integer code;

    /**
     * 返回数据对象 data
     */
    private T data;

    /**
     * 时间戳 (毫秒)
     */
    private long timestamp;

    // 强制通过静态工厂方法创建
    private Result() {
        this.timestamp = Instant.now().toEpochMilli();
    }

    /**
     * 辅助方法：设置成功的基础属性。
     * @return 当前 Result 对象
     */
    private Result<T> applySuccessDefaults() {
        this.success = true;
        this.code = SystemConstant.RESULT_SUCCESS_CODE_200;
        this.message = SystemConstant.RESULT_SUCCESS_MESSAGE;
        return this;
    }

    /**
     * 辅助方法：设置失败的基础属性。
     * @param errorCode 错误码
     * @param errorMessage 错误消息
     * @return 当前 Result 对象
     */
    private Result<T> applyErrorDefaults(int errorCode, String errorMessage) {
        this.success = false;
        this.code = errorCode;
        this.message = errorMessage;
        return this;
    }

    /**
     * 返回一个成功的Result对象，带默认消息且无数据。
     * @param <T> 数据类型
     * @return Result对象
     */
    public static <T> Result<T> success() {
        return new Result<T>().applySuccessDefaults();
    }

    /**
     * 返回一个成功的Result对象，带自定义消息且无数据。
     * @param message 自定义成功消息
     * @param <T> 数据类型
     * @return Result对象
     */
    public static <T> Result<T> success(String message) {
        return new Result<T>().applySuccessDefaults().setMessage(message);
    }

    /**
     * 返回一个成功的Result对象，带返回数据且默认消息。
     * @param data 返回的数据对象
     * @param <T> 数据类型
     * @return Result对象
     */
    public static <T> Result<T> success(T data) {
        return new Result<T>().applySuccessDefaults().setData(data);
    }

    /**
     * 返回一个成功的Result对象，带自定义消息和返回数据。
     * @param message 自定义成功消息
     * @param data 返回的数据对象
     * @param <T> 数据类型
     * @return Result对象
     */
    public static <T> Result<T> success(String message, T data) {
        return new Result<T>().applySuccessDefaults().setMessage(message).setData(data);
    }

    // --- 静态工厂方法：错误响应 ---

    /**
     * 返回一个带有默认错误码（500）和消息的失败Result对象。
     * @param <T> 数据类型
     * @return Result对象
     */
    public static <T> Result<T> error() {
        return new Result<T>().applyErrorDefaults(SystemConstant.RESULT_ERROR_CODE_500, SystemConstant.RESULT_ERROR_MESSAGE);
    }

    /**
     * 返回一个带有默认错误码（500）和自定义消息的失败Result对象。
     * @param message 错误消息
     * @param <T> 数据类型
     * @return Result对象
     */
    public static <T> Result<T> error(String message) {
        return new Result<T>().applyErrorDefaults(SystemConstant.RESULT_ERROR_CODE_500, message);
    }

    /**
     * 返回一个带有指定错误码和消息的失败Result对象。
     * @param code 错误码
     * @param message 错误消息
     * @param <T> 数据类型
     * @return Result对象
     */
    public static <T> Result<T> error(int code, String message) {
        return new Result<T>().applyErrorDefaults(code, message);
    }

    /**
     * 返回一个带有指定错误码（500）、消息和数据的失败Result对象。
     * @param message 错误消息
     * @param data 错误相关的可选数据
     * @param <T> 数据类型
     * @return Result对象
     */
    public static <T> Result<T> error(String message, T data) {
        return new Result<T>().applyErrorDefaults(SystemConstant.RESULT_ERROR_CODE_500, message).setData(data);
    }

    /**
     * 返回一个表示未授权（401）的失败Result对象。
     * @param message 错误消息
     * @param <T> 数据类型
     * @return Result对象
     */
    public static <T> Result<T> unauthorized(String message) {
        return error(SystemConstant.RESULT_UNAUTHORIZED_CODE_401, message);
    }

    /**
     * 返回一个表示禁止访问（403）的失败Result对象。
     * @param message 错误消息
     * @param <T> 数据类型
     * @return Result对象
     */
    public static <T> Result<T> forbidden(String message) {
        return error(SystemConstant.RESULT_FORBIDDEN_CODE_403, message);
    }
}
